UNPKG

7.86 kBJavaScriptView Raw
1 /***
2 * A control to add a Column Picker (right+click on any column header to reveal the column picker)
3 *
4 * USAGE:
5 *
6 * Add the slick.columnpicker.(js|css) files and register it with the grid.
7 *
8 * Available options, by defining a columnPicker object:
9 *
10 * var options = {
11 * enableCellNavigation: true,
12 * columnPicker: {
13 * columnTitle: "Columns", // default to empty string
14 *
15 * // the last 2 checkboxes titles
16 * hideForceFitButton: false, // show/hide checkbox near the end "Force Fit Columns" (default:false)
17 * hideSyncResizeButton: false, // show/hide checkbox near the end "Synchronous Resize" (default:false)
18 * forceFitTitle: "Force fit columns", // default to "Force fit columns"
19 * syncResizeTitle: "Synchronous resize", // default to "Synchronous resize"
20 * }
21 * };
22 *
23 * @class Slick.Controls.ColumnPicker
24 * @constructor
25 */
26
27'use strict';
28
29(function ($) {
30 function SlickColumnPicker(columns, grid, options) {
31 var _grid = grid;
32 var $list;
33 var $menu;
34 var columnCheckboxes;
35 var onColumnsChanged = new Slick.Event();
36
37 var defaults = {
38 fadeSpeed: 250,
39
40 // the last 2 checkboxes titles
41 hideForceFitButton: false,
42 hideSyncResizeButton: false,
43 forceFitTitle: "Force fit columns",
44 syncResizeTitle: "Synchronous resize"
45 };
46
47 function init(grid) {
48 grid.onHeaderContextMenu.subscribe(handleHeaderContextMenu);
49 grid.onColumnsReordered.subscribe(updateColumnOrder);
50 options = $.extend({}, defaults, options);
51
52 $menu = $("<div class='slick-columnpicker' style='display:none' />").appendTo(document.body);
53 var $close = $("<button type='button' class='close' data-dismiss='slick-columnpicker' aria-label='Close'><span class='close' aria-hidden='true'>&times;</span></button>").appendTo($menu);
54
55 // user could pass a title on top of the columns list
56 if(options.columnPickerTitle || (options.columnPicker && options.columnPicker.columnTitle)) {
57 var columnTitle = options.columnPickerTitle || options.columnPicker.columnTitle;
58 var $title = $("<div class='title'/>").append(columnTitle);
59 $title.appendTo($menu);
60 }
61
62 $menu.on("click", updateColumn);
63 $list = $("<span class='slick-columnpicker-list' />");
64
65 // Hide the menu on outside click.
66 $(document.body).on("mousedown", handleBodyMouseDown);
67
68 // destroy the picker if user leaves the page
69 $(window).on("beforeunload", destroy);
70 }
71
72 function destroy() {
73 _grid.onHeaderContextMenu.unsubscribe(handleHeaderContextMenu);
74 _grid.onColumnsReordered.unsubscribe(updateColumnOrder);
75 $(document.body).off("mousedown", handleBodyMouseDown);
76 $("div.slick-columnpicker").hide(options.fadeSpeed);
77 $menu.remove();
78 }
79
80 function handleBodyMouseDown(e) {
81 if (($menu && $menu[0] != e.target && !$.contains($menu[0], e.target)) || e.target.className == "close") {
82 $menu.hide(options.fadeSpeed);
83 }
84 }
85
86 function handleHeaderContextMenu(e, args) {
87 e.preventDefault();
88 $list.empty();
89 updateColumnOrder();
90 columnCheckboxes = [];
91
92 var $li, $input;
93 for (var i = 0; i < columns.length; i++) {
94 $li = $("<li />").appendTo($list);
95 $input = $("<input type='checkbox' />").data("column-id", columns[i].id);
96 columnCheckboxes.push($input);
97
98 if (_grid.getColumnIndex(columns[i].id) != null) {
99 $input.attr("checked", "checked");
100 }
101
102 $("<label />")
103 .html(columns[i].name)
104 .prepend($input)
105 .appendTo($li);
106 }
107
108 if (options.columnPicker && (!options.columnPicker.hideForceFitButton || !options.columnPicker.hideSyncResizeButton)) {
109 $("<hr/>").appendTo($list);
110 }
111
112 if (!(options.columnPicker && options.columnPicker.hideForceFitButton)) {
113 var forceFitTitle = (options.columnPicker && options.columnPicker.forceFitTitle) || options.forceFitTitle;
114 $li = $("<li />").appendTo($list);
115 $input = $("<input type='checkbox' />").data("option", "autoresize");
116 $("<label />")
117 .text(forceFitTitle)
118 .prepend($input)
119 .appendTo($li);
120 if (_grid.getOptions().forceFitColumns) {
121 $input.attr("checked", "checked");
122 }
123 }
124
125 if (!(options.columnPicker && options.columnPicker.hideSyncResizeButton)) {
126 var syncResizeTitle = (options.columnPicker && options.columnPicker.syncResizeTitle) || options.syncResizeTitle;
127 $li = $("<li />").appendTo($list);
128 $input = $("<input type='checkbox' />").data("option", "syncresize");
129 $("<label />")
130 .text(syncResizeTitle)
131 .prepend($input)
132 .appendTo($li);
133 if (_grid.getOptions().syncColumnCellResize) {
134 $input.attr("checked", "checked");
135 }
136 }
137
138 $menu
139 .css("top", e.pageY - 10)
140 .css("left", e.pageX - 10)
141 .css("max-height", $(window).height() - e.pageY -10)
142 .fadeIn(options.fadeSpeed);
143
144 $list.appendTo($menu);
145 }
146
147 function updateColumnOrder() {
148 // Because columns can be reordered, we have to update the `columns`
149 // to reflect the new order, however we can't just take `grid.getColumns()`,
150 // as it does not include columns currently hidden by the picker.
151 // We create a new `columns` structure by leaving currently-hidden
152 // columns in their original ordinal position and interleaving the results
153 // of the current column sort.
154 var current = _grid.getColumns().slice(0);
155 var ordered = new Array(columns.length);
156 for (var i = 0; i < ordered.length; i++) {
157 if ( _grid.getColumnIndex(columns[i].id) === undefined ) {
158 // If the column doesn't return a value from getColumnIndex,
159 // it is hidden. Leave it in this position.
160 ordered[i] = columns[i];
161 } else {
162 // Otherwise, grab the next visible column.
163 ordered[i] = current.shift();
164 }
165 }
166 columns = ordered;
167 }
168
169 function updateColumn(e) {
170 if ($(e.target).data("option") == "autoresize") {
171 if (e.target.checked) {
172 _grid.setOptions({forceFitColumns:true});
173 _grid.autosizeColumns();
174 } else {
175 _grid.setOptions({forceFitColumns:false});
176 }
177 return;
178 }
179
180 if ($(e.target).data("option") == "syncresize") {
181 if (e.target.checked) {
182 _grid.setOptions({syncColumnCellResize:true});
183 } else {
184 _grid.setOptions({syncColumnCellResize:false});
185 }
186 return;
187 }
188
189 if ($(e.target).is(":checkbox")) {
190 var visibleColumns = [];
191 $.each(columnCheckboxes, function (i, e) {
192 if ($(this).is(":checked")) {
193 visibleColumns.push(columns[i]);
194 }
195 });
196
197 if (!visibleColumns.length) {
198 $(e.target).attr("checked", "checked");
199 return;
200 }
201
202 _grid.setColumns(visibleColumns);
203 onColumnsChanged.notify({columns: visibleColumns, grid: _grid});
204 }
205 }
206
207 function getAllColumns() {
208 return columns;
209 }
210
211 init(_grid);
212
213 return {
214 "init": init,
215 "getAllColumns": getAllColumns,
216 "destroy": destroy,
217 "onColumnsChanged": onColumnsChanged
218 };
219 }
220
221 // Slick.Controls.ColumnPicker
222 $.extend(true, window, { Slick:{ Controls:{ ColumnPicker:SlickColumnPicker }}});
223})(jQuery);